package service

import (
	"github.com/pkg/errors"
	"mime/multipart"
	"strconv"
	"strings"
	"time"
	"trpg-base/dto"
	"trpg-base/entity"
	"trpg-common/constants"
	common_dto "trpg-common/dto"
	"trpg-common/logger"
	"trpg-common/utils/gorm_util"
	"trpg-common/utils/json_util"
	"trpg-common/utils/md5_util"
	"trpg-common/utils/oss_util"
	"trpg-common/utils/redis_util"
	"trpg-common/utils/snowflake_util"
	"trpg-common/utils/time_util"
)

const expiration = 24 * time.Hour // 过期时间默认为1天

type UserService struct{}

func (s UserService) LogIn(user entity.User) *dto.UserDTO {
	user.IsDeleted = constants.DeleteNo
	gorm_util.SelectOneByCondition(&user)
	if user.Id != 0 && user.Uid != "" {
		session := md5_util.Md5Bytes(json_util.Marshal(&user))
		// 获取用户头像
		user.AvatarUrl = oss_util.GetUrlByKey(user.AvatarPath)
		// 写入redis
		redis_util.SetStruct(session, user, expiration)
		user.Session = session
		return &dto.UserDTO{
			Uid:       user.Uid,
			Phone:     user.Phone,
			Username:  user.Username,
			AvatarUrl: user.AvatarUrl,
			Session:   user.Session,
		}
	}
	logger.Logger.Panicf("%v", errors.New("用户不存在，手机号或密码错误"))
	return nil
}

func (s UserService) Register(user entity.User) *dto.UserDTO {
	// 查看手机号以及用户名是否重复
	repeatUser := entity.User{
		Phone: user.Phone,
	}
	repeatUser.IsDeleted = constants.DeleteNo
	gorm_util.SelectOneByCondition(&repeatUser)
	if repeatUser.Id != 0 && repeatUser.Uid != "" {
		logger.Logger.Panicf("%+v", errors.New("手机号重复，请重新填写"))
	}
	repeatUser = entity.User{
		Username: user.Username,
	}
	repeatUser.IsDeleted = constants.DeleteNo
	gorm_util.SelectOneByCondition(&repeatUser)
	if repeatUser.Id != 0 && repeatUser.Uid != "" {
		logger.Logger.Panicf("%+v", errors.New("用户名已经被占用，请重新填写"))
	}
	// 生成雪花id
	user.Uid = strconv.FormatInt(snowflake_util.SnowFlakeID(), 10)
	user.GmtCreated = time_util.Now()
	user.GmtModified = time_util.Now()
	user.Creator = user.Uid
	user.Modifier = user.Uid
	user.IsDeleted = constants.DeleteNo
	user.AvatarPath = "/avatar/default_avatar.jpg"
	user.AvatarUrl = oss_util.GetUrlByKey(user.AvatarPath)
	// 写入数据库
	gorm_util.InsertUpdateOne(&user)
	session := md5_util.Md5Bytes(json_util.Marshal(&user))
	// 写入redis
	redis_util.SetStruct(session, user, expiration)
	user.Session = session
	return &dto.UserDTO{
		Uid:       user.Uid,
		Phone:     user.Phone,
		Username:  user.Username,
		AvatarUrl: user.AvatarUrl,
		Session:   user.Session,
	}
}

func (s UserService) UpdateInfo(user entity.User, session string) {
	user.GmtModified = time_util.Now()
	user.Modifier = user.Uid
	// 查看手机号以及用户名是否重复
	repeatUser := entity.User{}
	gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).Eq("phone", user.Phone).Eq("is_deleted", constants.DeleteNo).NotEq("uid", user.Uid), &repeatUser)
	if repeatUser.Id != 0 && repeatUser.Uid != "" {
		logger.Logger.Panicf("%+v", errors.New("手机号重复，请重新填写"))
	}
	repeatUser = entity.User{}
	gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).Eq("username", user.Username).Eq("is_deleted", constants.DeleteNo).NotEq("uid", user.Uid), &repeatUser)
	if repeatUser.Id != 0 && repeatUser.Uid != "" {
		logger.Logger.Panicf("%+v", errors.New("用户名已经被占用，请重新填写"))
	}
	// 修改数据库
	gorm_util.UpdateBatchByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).Eq("uid", user.Uid), &user)
	// 修改redis
	redis_util.Remove(session)
	redis_util.SetStruct(session, user, expiration)
}

func (s UserService) UploadAvatar(file *multipart.FileHeader, user common_dto.UserInfo) string {
	split := strings.Split(file.Filename, ".")
	suffix := split[len(split)-1]
	avatarPath := "/avatar/" + user.Uid + "." + suffix
	url := oss_util.UploadMultiFile(file, avatarPath)
	userEntity := entity.User{}
	userEntity.AvatarPath = avatarPath
	userEntity.Modifier = user.Uid
	userEntity.GmtModified = time_util.Now()
	// 修改库
	gorm_util.UpdateBatchByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).Eq("uid", user.Uid), &userEntity)
	return url
}

func (s UserService) GetUserIdNameMapByUidList(uidList []string) map[string]string {
	users := make([]entity.User, 0)
	gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).In("uid", uidList).Eq("is_deleted", constants.DeleteNo), &users)
	res := make(map[string]string)
	for _, user := range users {
		res[user.Uid] = user.Username
	}
	return res
}

func (s UserService) GetUserMapByUidList(uidList []string) map[string]common_dto.UserInfo {
	users := make([]entity.User, 0)
	gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).In("uid", uidList).Eq("is_deleted", constants.DeleteNo), &users)
	res := make(map[string]common_dto.UserInfo)
	for _, user := range users {
		res[user.Uid] = common_dto.UserInfo{
			Uid:      user.Uid,
			Phone:    user.Phone,
			Username: user.Username,
			Avatar:   oss_util.GetUrlByKey(user.AvatarPath),
		}
	}
	return res
}

func (s UserService) GetUserByUid(uid string) common_dto.UserInfo {
	user := entity.User{}
	gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.User{}).Eq("uid", uid).Eq("is_deleted", constants.DeleteNo), &user)
	res := common_dto.UserInfo{
		Uid:      user.Uid,
		Phone:    user.Phone,
		Username: user.Username,
		Avatar:   oss_util.GetUrlByKey(user.AvatarPath),
	}
	return res
}
